﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace EvoAlgLib
{
    public abstract class GenArrayIndividual : Individual
    {
        protected static int LENGTH = 0;
        protected int[] genotype;
        protected double p_mutate;
        protected double fitness;
        protected bool needsCalcFit;
        protected int age;

        public GenArrayIndividual(double mutate)
        {
            this.age = 0;
            this.p_mutate = mutate;
            this.needsCalcFit = true;
        }

        public GenArrayIndividual(GenArrayIndividual other)
        {
            this.age = 0;
            this.genotype = new int[other.genotype.Length];
            for (int i = 0; i < this.genotype.Length; ++i)
            {
                this.genotype[i] = other.genotype[i];
            }
            this.p_mutate = other.p_mutate;
            this.needsCalcFit = true;
        }

        public double getFitness()
        {
            if (this.needsCalcFit)
            {
                calcFit();
                this.needsCalcFit = false;
            }
            return fitness;
        }

        protected abstract void calcFit();

        protected abstract void slotMutate(int ind);

        public virtual Individual mutate()
        {
            for (int i = 0; i < this.genotype.Length; ++i)
            {
                double r = LibStatics.getRandomizer().NextDouble();
                if (r < this.p_mutate)
                {
                    slotMutate(i);
                }
            }
            this.needsCalcFit = true;
            return this;
        }

        public static void setLength(int length)
        {
            LENGTH = length;
        }

        public object getGenotype()
        {
            return this.genotype;
        }

        int IComparable.CompareTo(object obj)
        {
            GenArrayIndividual other = (GenArrayIndividual)obj;
            if (this.fitness > other.fitness)
                return 1;
            if (this.fitness < other.fitness)
                return -1;
            return 0;
        }

        public abstract String plotDisplay();

        public override string ToString()
        {
            string ans = "[";
            for (int i = 0; i < this.genotype.Length - 1; ++i) ans += this.genotype[i] + ",";
            ans += this.genotype[this.genotype.Length - 1] + "]";
            return ans;
        }


        public int getAge()
        {
            return age;
        }

        public void incAge()
        {
            age++;
        }
    }
}
